/**
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.api.adwords.starterkit.examples;

import com.google.api.adwords.starterkit.StarterKit;
import com.google.api.adwords.starterkit.db.structures.CriterionStructure;
import com.google.api.adwords.starterkit.db.structures.GeoTargetStructure;
import com.google.api.adwords.starterkit.db.structures.LanguageTargetStructure;
import com.google.api.adwords.starterkit.db.structures.NetworkTargetStructure;
import com.google.api.adwords.starterkit.settings.AdGroupSettings;
import com.google.api.adwords.starterkit.settings.CampaignSettings;
import com.google.api.adwords.starterkit.settings.KeywordSettings;
import com.google.api.adwords.starterkit.settings.StarterKitSettings;
import com.google.api.adwords.starterkit.settings.TextAdSettings;
import com.google.api.adwords.starterkit.wrappers.AdGroupWrapper;
import com.google.api.adwords.starterkit.wrappers.CampaignWrapper;
import com.google.api.adwords.starterkit.wrappers.KeywordWrapper;
import com.google.api.adwords.v201101.cm.AdGroupStatus;
import com.google.api.adwords.v201101.cm.CampaignStatus;
import com.google.api.adwords.v201101.cm.KeywordMatchType;
import com.google.api.adwords.v201101.cm.UserStatus;

import au.com.bytecode.opencsv.CSVReader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;

/**
 * The Class ImportFromCSV is a demo that creates campaigns based on the 
 * content of a CSV file.
 *  
 * @author rodrigo.f.vale@gmail.com  (Rodrigo Vale)
 */
public class ImportFromCSV {
  public static final int NONE = 0;
  public static final int CAMPAIGN = 1;
  public static final int ADGROUP = 2;
  public static final int KEYWORD = 3;
  public static final int TEXTAD = 4;
  public static final int CAMPAIGN_NKEYWORD = 5;
  public static final int ADGROUP_NKEYWORD = 6;
    
  public static void howToUse() {
    System.out.print(
        "SYNOPSIS\n" +
        "       ImportFromCSV [SETTINGS] [CSV_FILE]\n" +
        "\n" +
        "DESCRIPTION\n" +
        "       This demo creates campaigns based on the content of a CSV\n" +
        "file.\n" +
        "\n" +
        "EXAMPLE\n" +
        "       java starterkit.jar ImportFromCSV settings.xml " +
        "Campaigns.csv\n");
    System.exit(0);
  }
  
  /**
   * Uses the CSV header line to capture fields values 
   *
   * @param header the CSV header line map
   * @param fields the array associated to the current CSV line
   * @param field the field to be returned  
   * @return the field value  
   */
  public static String getField(HashMap<String, Integer> header, 
      String [] fields, String field) {
    if (header.containsKey(field)) {
      int index = header.get(field);
      if (index < fields.length) {
        return fields[index];
      }
    }
    return "";
  }
  
  /**
   * Convert the campaign geo localization from the String format to 
   * GeoTargetStructure format 
   *
   * @param geo the campaign geo localization in the String format 
   * @return the campaign geo localization in GeoTargetStructure format  
   */
  public static GeoTargetStructure createGeotarget(String geo) {
    GeoTargetStructure geoTarget = new GeoTargetStructure();
    if (geo.matches("\\w\\w")) {    
      geoTarget.setCountryCode(geo);
    }
    if (geo.matches("\\w\\w\\-\\w\\w")) {
      geoTarget.setProvinceCode(geo);
    }
    if (geo.matches("[\\w\\s]+\\,[\\w\\s]+")) {
      String cityName = geo;
      String pc = geo.split(",")[1];
      pc = pc.trim();
      String provinceCode = pc.split(" ")[0];
      String countryCode = pc.split(" ")[1];

      geoTarget.setCityName(cityName);
      geoTarget.setProvinceCode(provinceCode);
      geoTarget.setCountryCode(countryCode);
    }
    if (geo.matches("\\-\\w\\w")) {
      geoTarget.setCountryCode(geo);
      geoTarget.setExclude(true);
    }
    if (geo.matches("\\-\\w\\w\\-\\w\\w")) {
      geoTarget.setProvinceCode(geo);
      geoTarget.setExclude(true);
    }
    if (geo.matches("\\-[\\w\\s]+\\,[\\w\\s]+")) {
      geo = geo.substring(1);
      String cityName = geo;
      String pc = geo.split(",")[1];
      pc = pc.trim();
      String provinceCode = pc.split(" ")[0];
      String countryCode = pc.split(" ")[1];

      geoTarget.setCityName(cityName);
      geoTarget.setProvinceCode(provinceCode);
      geoTarget.setCountryCode(countryCode);
      geoTarget.setExclude(true);
    }
    return geoTarget;
  }
  
  /**
   * Check the CSV line to determinate if the line is adding information
   * about Campaign, AdGroup, Keyword, TextAd or Negative Keyword
   *
   * @return the type of CSV line
   */
  public static int getType(String campaign, String adgroup, String keyword, 
      String headline, String nKeyword) {
    int type = NONE; 
    if ((campaign.length() > 0) && (adgroup.length() == 0) 
      && (keyword.length() == 0) && (headline.length() == 0) 
      && (nKeyword.length() == 0)) {
      type = CAMPAIGN;
    } else if ((campaign.length() > 0) && (adgroup.length() > 0) 
        && (keyword.length() == 0) && (headline.length() == 0)
        && (nKeyword.length() == 0)) {
      type = ADGROUP;
    } else if ((campaign.length() > 0) && (adgroup.length() > 0) 
        && (keyword.length() > 0) && (headline.length() == 0)
        && (nKeyword.length() == 0)) {
      type = KEYWORD;
    } else if ((campaign.length() > 0) && (adgroup.length() > 0) 
        && (keyword.length() == 0) && (headline.length() > 0)
        && (nKeyword.length() == 0)) {
      type = TEXTAD;
    } else if ((campaign.length() > 0) && (adgroup.length() == 0) 
        && (keyword.length() == 0) && (headline.length() == 0) 
        && (nKeyword.length() > 0)) {
        type = CAMPAIGN_NKEYWORD;
    } else if ((campaign.length() > 0) && (adgroup.length() > 0) 
        && (keyword.length() == 0) && (headline.length() == 0) 
        && (nKeyword.length() > 0)) {
        type = ADGROUP_NKEYWORD;
    }
    return type;
  }
  
  /**
   * @param args
   */
  public static void main(String[] args) throws IOException {
    if (args.length < 2) {
      howToUse();
    }
    String settingsFile = args[0];
    String csvFile = args[1];
    String [] fields;

    StarterKitSettings starterKitSettings 
        = new StarterKitSettings(settingsFile);
    CampaignSettings campaignSettings 
        = starterKitSettings.getCampaignSettings();
    AdGroupSettings adGroupSettings = starterKitSettings.getAdGroupSettings();
    KeywordSettings keywordSettings = starterKitSettings.getKeywordSettings();
    TextAdSettings textAdSettings = starterKitSettings.getTextAdSettings();
    
    StarterKit starterKit = new StarterKit(starterKitSettings);
    starterKit.load();

    // open the CSV file to be processed 
    CSVReader reader = null; 
    try {
      reader = new CSVReader(new FileReader(csvFile));
    } catch (FileNotFoundException e) {
      System.out.println("Error loading CSV file");
      System.exit(1);
    }
    
    // gets the header line and process it
    fields = reader.readNext();
    HashMap<String, Integer> header = new HashMap<String, Integer>();
    int count = 0;
    for (String field : fields) {
      header.put(field, count);
      count++;
    }
    
    // process the CSV content
    while ((fields = reader.readNext()) != null) {
      String campaign = getField(header, fields, "Campaign");
      String campaignDailyBudget = getField(header, fields, 
          "Campaign Daily Budget");      
      String biddingStrategy = getField(header, fields, "Bidding Strategy");
      String pricingModel = getField(header, fields, "Pricing Model");
      String bidCeiling = getField(header, fields, "Bid Ceiling");
      String languages = getField(header, fields, "Languages");
      String geoTargeting = getField(header, fields, "Geo Targeting");
      String networkTarget = getField(header, fields, "Network Target");
      String adGroup = getField(header, fields, "Ad Group");
      String maxCPC = getField(header, fields, "Max CPC");
      String maxCPM = getField(header, fields, "Max CPM");
      String maxCPA = getField(header, fields, "Max CPA");
      String keyword = getField(header, fields, "Keyword");
      String keywordType 
          = getField(header, fields, "Keyword Type").toUpperCase();
      String headline = getField(header, fields, "Headline");
      String descriptionLine1 = getField(header, fields, "Description Line 1");
      String descriptionLine2 = getField(header, fields, "Description Line 2");
      String displayURL = getField(header, fields, "Display URL");
      String destinationURL = getField(header, fields, "Destination URL");
      String campaignStatus = getField(header, fields, "Campaign Status");
      String adGroupStatus = getField(header, fields, "AdGroup Status");
      String keywordStatus = getField(header, fields, "Keyword Status");
      String adParam1 = getField(header, fields, "AdParam1");
      String adParam2 = getField(header, fields, "AdParam2");
      String nKeyword = getField(header, fields, "Negative Keywords");
      String nKeywordType 
          = getField(header, fields, "Negative Keyword Type").toUpperCase();
      
      int type = getType(campaign, adGroup, keyword, headline, nKeyword);

      // Campaign specification
      if (type == CAMPAIGN) {
        if (campaignDailyBudget.length() > 0) {
          float floatBudget = Float.parseFloat(campaignDailyBudget);
          long budget = (long) (floatBudget * 1000000); 
          campaignSettings.setBudget(budget);
        }
        
        HashSet<LanguageTargetStructure> languageTarget 
            = new HashSet<LanguageTargetStructure>();
        if (languages.length() > 0) {
          String[] languageArray = languages.split(";");
          for (int i = 0; i < languageArray.length; i++) {
            LanguageTargetStructure languageTargetStructure 
                = new LanguageTargetStructure(0, 0, languageArray[i]);
            languageTarget.add(languageTargetStructure);
          }          
        }
        campaignSettings.setLanguageTarget(languageTarget);
        campaignSettings.setBiddingStrategy(biddingStrategy);
        if (bidCeiling.length() > 0) {
          campaignSettings.setBidCeiling(Long.parseLong(bidCeiling));
        }
        campaignSettings.setPricingModel(pricingModel);
        
        String[] networkTargets = networkTarget.split(";");
        HashSet<NetworkTargetStructure> networkTargetList 
            = new HashSet<NetworkTargetStructure>();
        for (String target : networkTargets) {
          NetworkTargetStructure networkTargetStructure 
              = new NetworkTargetStructure();
          networkTargetStructure.setNetwork(target);
          networkTargetList.add(networkTargetStructure);
        }
        campaignSettings.setNetworkTarget(networkTargetList);
                
        HashSet<GeoTargetStructure> geoTargetSettings = 
          new HashSet<GeoTargetStructure>(); 
        if (geoTargeting.length() > 0) {          
          String[] geoTargetingArray = geoTargeting.split(";");
          for (String geo : geoTargetingArray) {
            GeoTargetStructure geoTarget = createGeotarget(geo);
            geoTargetSettings.add(geoTarget);
          }
          campaignSettings.setGeoTarget(geoTargetSettings);
          campaignSettings.setStatus(campaignStatus);
          //add campaign
          starterKit.getCampaignWrapper(campaign, campaignSettings);
        }
      } else if (type == ADGROUP) {
        CampaignWrapper campaignWrapper = 
            starterKit.getCampaignWrapper(campaign, campaignSettings);
        
        if (maxCPC.length() > 0) {
          float floatCpc = Float.parseFloat(maxCPC);
          long cpc = (long) (floatCpc * 1000000); 
          adGroupSettings.setCpc(cpc);
        } else if (maxCPM.length() > 0) {
          float floatCpm = Float.parseFloat(maxCPM);
          long cpm = (long) (floatCpm * 1000000);
          adGroupSettings.setCpm(cpm);
        } else if (maxCPA.length() > 0) {
          float floatCpa = Float.parseFloat(maxCPA);
          long cpa = (long) (floatCpa * 1000000);
          adGroupSettings.setCpa(cpa);          
        } else {
          System.out.println("This demo is not compatible with this " +
            "bid strategy");
          System.exit(1);
        }
        adGroupSettings.setStatus(adGroupStatus);
        campaignWrapper.getAdGroupWrapper(adGroup, adGroupSettings);
      } else if (type == KEYWORD) {
        CampaignWrapper campaignWrapper = 
          starterKit.getCampaignWrapper(campaign, campaignSettings);
        
        // gets the adGroup and ignores the settings
        AdGroupWrapper adGroupWrapper = 
          campaignWrapper.getAdGroupWrapper(adGroup, adGroupSettings);
        
        keywordSettings.setMatchType(keywordType);
        
        if (maxCPC.length() > 0) {
          long cpc = 0;
          float fcpc = Float.parseFloat(maxCPC);
          fcpc = fcpc * 1000000;
          cpc = (long) fcpc; 
          keywordSettings.setCpc(cpc);
        }
        
        if (maxCPM.length() > 0) {
          long cpm = 0;
          float fcpm = Float.parseFloat(maxCPM);
          fcpm = fcpm * 1000000;
          cpm = (long) fcpm; 
          keywordSettings.setCpm(cpm);
        }
        
        keywordSettings.setStatus(keywordStatus);
        KeywordWrapper kwdWrapper = 
          adGroupWrapper.getKeywordWrapper(keyword, false, destinationURL, 
          keywordSettings);
        
        kwdWrapper.getKeywordParamWrapper(adParam1, adParam2);        
      } else if (type == TEXTAD) {
        CampaignWrapper campaignWrapper = 
            starterKit.getCampaignWrapper(campaign, campaignSettings);
        
        AdGroupWrapper adGroupWrapper = 
            campaignWrapper.getAdGroupWrapper(adGroup, adGroupSettings);
        
        textAdSettings.setDisplayUrl(displayURL);
        adGroupWrapper.getTextWrapper(headline, descriptionLine1, 
            descriptionLine2, destinationURL, textAdSettings);        
      } else if (type == CAMPAIGN_NKEYWORD) {
        CriterionStructure.validateMatchType(nKeywordType);
        CampaignWrapper campaignWrapper = 
            starterKit.getCampaignWrapper(campaign, campaignSettings);        
        campaignWrapper.getNegativeKeywordWrapper(nKeyword, 
            KeywordMatchType.fromString(nKeywordType));
      } else if (type == ADGROUP_NKEYWORD) {
        CriterionStructure.validateMatchType(nKeywordType);
        CampaignWrapper campaignWrapper = 
            starterKit.getCampaignWrapper(campaign, campaignSettings);        
        AdGroupWrapper adGroupWrapper = 
            campaignWrapper.getAdGroupWrapper(adGroup, adGroupSettings);
        
        KeywordSettings nKeywordSettings = new KeywordSettings(false, 0, 0,
            UserStatus.ACTIVE, 
            KeywordMatchType.fromString(nKeywordType), 
            true, true, true, true);        
        adGroupWrapper.getKeywordWrapper(nKeyword, true, "", 
            nKeywordSettings);
      }
    }        
    starterKit.save();
    starterKit.done();
  }
}
